﻿using nadModel;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlTypes;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Text;

using System.Web;

namespace nadModel
{
    public abstract class AbstractEntityProcess : LogProcess
    {

        private const int int_0 = 0;
        private const int int_1 = 1;
        private const int int_2 = 30;
        private int int_3 = 1;

        private bool bool_0;
        public AbstractEntityProcess()
        {

        }


        public int FindCountByCustomizedWhereClause(AbstractEntity entity, string whereClause, params object[] object_0)
        {
            string string_ = "select count(*) from " + entity.ENTITY_TABLES + " with (nolock) " + AbstractEntityProcess.BindSqlParameter(whereClause, object_0);
            return (int)this.ExecuteScalar(string_);
        }
        public static string BindSqlParameter(string whereClause, params object[] object_0)
        {
            if (object_0 == null)
            {
                return whereClause;
            }

            int num = 0;
            int num2 = 0;
            List<string> list = new List<string>();
            StringBuilder stringBuilder = new StringBuilder();
            while (true)
            {
                num2 = whereClause.IndexOf("@", num);
                if (num2 < 0)
                {
                    break;
                }
                list.Add(whereClause.Substring(num, num2 - num));
                num = num2 + 1;
                stringBuilder.Length = 0;
                stringBuilder.Append("@");
                int i = num;
                while (i < whereClause.Length)
                {
                    bool flag;
                    if (flag = char.IsNumber(whereClause[i]))
                    {
                        stringBuilder.Append(whereClause[i]);
                        num++;
                    }
                    if (flag)
                    {
                        if (i != whereClause.Length - 1)
                        {
                            i++;
                            continue;
                        }
                    }
                    list.Add(stringBuilder.ToString());
                    break;
                }
            }
            list.Add(whereClause.Substring(num));
            for (int j = 0; j < list.Count; j++)
            {
                if (list[j].StartsWith("@") && int.TryParse(list[j].Substring(1), out num2) && num2 <= object_0.Length)
                {
                    object obj = object_0[num2 - 1];
                    if (obj == null)
                    {
                        list[j] = "null";
                    }
                    else
                    {
                        if (obj is string)
                        {
                            list[j] = "N'" + DbTypeHelper.GetString(obj).Replace("'", "''") + "'";
                        }
                        else
                        {
                            if (obj is string)
                            {
                                list[j] = "'" + DbTypeHelper.GetString(obj).Replace("'", "''") + "'";
                            }
                            else
                            {
                                if (!(obj is DateTime) && !(obj is SqlDateTime))
                                {
                                    list[j] = obj.ToString();
                                }
                                else
                                {
                                    list[j] = "'" + DbTypeHelper.GetString(obj).Replace("'", "''") + "'";
                                }
                            }
                        }
                    }
                }
            }
            return string.Join(string.Empty, list.ToArray());
        }

        public AbstractEntity[] FindBySql(string sql, string conection_addr)
        {
            AbstractEntity[] result;
            try
            {
                result = PackEntity(ExecuteReader(sql, conection_addr));
            }
            catch (Exception ex)
            {
                base.Log(DbConnectionHelper.GetInstance().GetConnectionString(), LogLevel.ERROR);
                base.Log(ex.ToString(), LogLevel.ERROR);
                throw ex;
            }
            finally
            {

            }
            return result;
        }

        public object ExecuteScalar(string string_0)
        {
            object result = null;
            try
            {
                //IDbConnection conn = this.OpenConnection();
                //IDbCommand command = this.GetCommand(string_0, conn);
                //if (this.commandTimeout > 0)
                //{
                //    command.CommandTimeout = this.commandTimeout;
                //}
                //object obj = command.ExecuteScalar();
                //this.CloseConnection();
                //result = obj;
            }
            catch (Exception ex)
            {
                base.Log(ex.ToString(), LogLevel.ERROR);
                throw ex;
            }
            finally
            {

            }
            return result;
        }

        private string method_2(AbstractEntity abstractEntity_0)
        {
            StringBuilder stringBuilder = new StringBuilder();
            bool flag = true;
            Type type = abstractEntity_0.PKey.GetType();
            string[] fieldList = abstractEntity_0.PKey.GetFieldList();
            string[] array = fieldList;
            for (int i = 0; i < array.Length; i++)
            {
                string text = array[i];
                if (!flag)
                {
                    stringBuilder.Append(" and ");
                }
                flag = false;
                stringBuilder.Append(text);
                stringBuilder.Append("='");
                stringBuilder.Append(DbConnectionHelper.SqlEscape(DbTypeHelper.GetString(type.GetProperty(this.FieldNameToPropertyName(text)).GetValue(abstractEntity_0.PKey, null))));
                stringBuilder.Append("'");
            }
            return stringBuilder.ToString();
        }
        public virtual void InsertEntity(AbstractEntity entity)
        {
            string[] fieldList = entity.GetFieldList();
            StringBuilder stringBuilder = new StringBuilder();
            try
            {
                if (entity.ENTITY_TABLE_COUNT > 1)
                {
                    Exception ex = new Exception("Cannot insert new record for multiple-table entity");
                    throw ex;
                }
                stringBuilder.Append("insert into ");
                stringBuilder.Append(entity.ENTITY_TABLES);
                stringBuilder.Append(" (");
                bool flag = true;
                string[] array = fieldList;
                for (int i = 0; i < array.Length; i++)
                {
                    string text = array[i];
                    if (!text.Equals(entity.PKey.IDENTITY_FIELD))
                    {
                        if (!flag)
                        {
                            stringBuilder.Append(", ");
                        }
                        flag = false;
                        stringBuilder.Append(text);
                    }
                }
                stringBuilder.Append(") values (");
                Type type = entity.GetType();
                flag = true;
                Dictionary<string, byte[]> dictionary = new Dictionary<string, byte[]>();
                string[] array2 = fieldList;
                for (int j = 0; j < array2.Length; j++)
                {
                    string text2 = array2[j];
                    if (!text2.Equals(entity.PKey.IDENTITY_FIELD))
                    {
                        if (!flag)
                        {
                            stringBuilder.Append(", ");
                        }
                        flag = false;
                        if (!text2.Equals(entity.CREATED_DATETIME_FIELD) && !text2.Equals(entity.UPDATED_DATETIME_FIELD))
                        {
                            PropertyInfo property = type.GetProperty(this.FieldNameToPropertyName(text2));
                            object value = property.GetValue(entity, null);
                            if (value != null && (!(value is INullable) || !((INullable)value).IsNull))
                            {
                                if (value is byte[])
                                {
                                    stringBuilder.Append("@" + text2);
                                    dictionary.Add("@" + text2, (byte[])value);
                                }
                                else
                                {
                                    if (value is string || value is SqlDateTime)
                                    {
                                        stringBuilder.Append("N'");
                                    }
                                    stringBuilder.Append(DbConnectionHelper.SqlEscape(DbTypeHelper.GetString(value)));
                                    if (value is string || value is SqlDateTime)
                                    {
                                        stringBuilder.Append("'");
                                    }
                                }
                            }
                            else
                            {
                                if (!text2.Equals(entity.CREATED_BY_FIELD) && !text2.Equals(entity.UPDATED_BY_FIELD))
                                {
                                    stringBuilder.Append("null");
                                }
                                else
                                {
                                    string currentContext = null;
                                    if (currentContext == null)
                                    {
                                        stringBuilder.Append("'nouser'");
                                    }
                                    else
                                    {
                                        stringBuilder.Append("admin");
                                    }
                                }
                            }
                        }
                        else
                        {
                            stringBuilder.Append("getdate()");
                        }
                    }
                }
                stringBuilder.Append(")");

                base.Log(stringBuilder.ToString(), LogLevel.INFO);
                //foreach (string current in dictionary.Keys)
                //{
                //    this.ipersistantUnit_0.BindVarBinary(ref command, current, dictionary[current]);
                //}
                //command.ExecuteNonQuery();
                type = entity.PKey.GetType();
                if (entity.PKey.IDENTITY_FIELD.Length > 0 && string.IsNullOrEmpty(entity.LinkedServerID))
                {
                    //  command.CommandText = "select scope_identity()";
                    //int num = decimal.ToInt32((decimal)command.ExecuteScalar());
                    PropertyInfo property = type.GetProperty(this.FieldNameToPropertyName(entity.PKey.IDENTITY_FIELD));
                    if (property != null)
                    {
                        //property.SetValue(entity.PKey, num, null);
                    }
                }
                entity.MarkClean();
            }
            catch (Exception ex2)
            {
                base.Log(ex2.ToString(), LogLevel.ERROR);
                throw ex2;
            }
            finally
            {

            }
        }
        protected void BuildUpdateSql(ref IDbCommand idbCommand_0, AbstractEntity entity)
        {
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.Append("update ");
            stringBuilder.Append(entity.ENTITY_TABLES);
            stringBuilder.Append(" set ");
            bool flag = true;
            Type type = entity.GetType();
            Dictionary<string, byte[]> dictionary = new Dictionary<string, byte[]>();
            foreach (string current in entity.DirtyFields)
            {
                if (!current.Equals(entity.CREATED_BY_FIELD) && !current.Equals(entity.CREATED_DATETIME_FIELD) && !current.Equals(entity.PKey.IDENTITY_FIELD))
                {
                    PropertyInfo property = type.GetProperty(this.FieldNameToPropertyName(current));
                    if (property != null)
                    {
                        object value = property.GetValue(entity, null);
                        if (!flag)
                        {
                            stringBuilder.Append(", ");
                        }
                        flag = false;
                        stringBuilder.Append(current);
                        stringBuilder.Append("=");
                        if (current.Equals(entity.UPDATED_DATETIME_FIELD))
                        {
                            stringBuilder.Append("getdate()");
                        }
                        else
                        {
                            if (current.Equals(entity.UPDATED_BY_FIELD))
                            {
                                string currentContext = null;
                                if (currentContext == null)
                                {
                                    stringBuilder.Append("'nouser'");
                                }
                                else
                                {
                                    stringBuilder.Append("admin");
                                }
                            }
                            else
                            {
                                if (value != null && (!(value is INullable) || !((INullable)value).IsNull))
                                {
                                    if (value is byte[])
                                    {
                                        stringBuilder.Append("@" + current);
                                        dictionary.Add("@" + current, (byte[])value);
                                    }
                                    else
                                    {
                                        if (value is string || value is SqlDateTime)
                                        {
                                            stringBuilder.Append("N'");
                                        }
                                        stringBuilder.Append(DbConnectionHelper.SqlEscape(DbTypeHelper.GetString(value)));
                                        if (value is string || value is SqlDateTime)
                                        {
                                            stringBuilder.Append("'");
                                        }
                                    }
                                }
                                else
                                {
                                    stringBuilder.Append("null");
                                }
                            }
                        }
                    }
                }
            }
            stringBuilder.Append(" where ");
            stringBuilder.Append(this.method_2(entity));
            idbCommand_0.CommandText = stringBuilder.ToString();
            foreach (string current2 in dictionary.Keys)
            {
                // this.ipersistantUnit_0.BindVarBinary(ref idbCommand_0, current2, dictionary[current2]);
            }
        }
        public string BuildVersionCheckSql(AbstractEntity entity, SqlDateTime updatedDatetime)
        {
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.Append("select count(*) from ");
            stringBuilder.Append(entity.ENTITY_TABLES);
            stringBuilder.Append(" where ");
            stringBuilder.Append(entity.UPDATED_DATETIME_FIELD);
            stringBuilder.Append(" > '");
            stringBuilder.Append(DbTypeHelper.GetString(updatedDatetime));
            stringBuilder.Append("' and ");
            stringBuilder.Append(this.method_2(entity));
            return stringBuilder.ToString();
        }
        private bool method_3(AbstractEntity abstractEntity_0, IDbCommand idbCommand_0)
        {
            Type type = abstractEntity_0.GetType();
            PropertyInfo property = type.GetProperty(this.FieldNameToPropertyName(abstractEntity_0.UPDATED_DATETIME_FIELD));
            if (property == null)
            {
                return false;
            }
            SqlDateTime updatedDatetime = (SqlDateTime)property.GetValue(abstractEntity_0, null);
            if (updatedDatetime.IsNull)
            {
                return false;
            }
            idbCommand_0.CommandText = this.BuildVersionCheckSql(abstractEntity_0, updatedDatetime);
            int num = (int)idbCommand_0.ExecuteScalar();
            return num > 0;
        }
        public virtual void UpdateEntity(AbstractEntity entity)
        {
            if (entity.DirtyFields.Count == 0)
            {
                return;
            }
            try
            {
                entity.MarkDirty(entity.UPDATED_DATETIME_FIELD);
                entity.MarkDirty(entity.UPDATED_BY_FIELD);
                //IDbCommand command = this.GetCommand("", this.OpenConnection());
                //if (this.commandTimeout > 0)
                //{
                //    command.CommandTimeout = this.commandTimeout;
                //}
                //if (entity.ENTITY_TABLE_COUNT > 1)
                //{
                //    ValidationException ex = new ValidationException("Cannot update multiple-table entity");
                //    throw ex;
                //}
                //if (this.method_3(entity, command))
                //{
                //    VersionExpiredException ex2 = new VersionExpiredException("Record updated by others.");
                //    throw ex2;
                //}
                //this.BuildUpdateSql(ref command, entity);
                //base.Log(command.CommandText, LogLevel.INFO);
                //command.ExecuteNonQuery();
                //entity.MarkClean();
                //this.CloseConnection();
            }
            catch (Exception ex3)
            {
                base.Log(ex3.ToString(), LogLevel.ERROR);
                throw ex3;
            }
            finally
            {

            }
        }
        public virtual void DeleteEntity(AbstractEntity entity)
        {
            StringBuilder stringBuilder = new StringBuilder();
            try
            {
                //IDbCommand command = this.GetCommand("", this.OpenConnection());
                //if (this.commandTimeout > 0)
                //{
                //    command.CommandTimeout = this.commandTimeout;
                //}
                //if (entity.ENTITY_TABLE_COUNT > 1)
                //{
                //    ValidationException ex = new ValidationException("Multiple-table entity are not supported");
                //    throw ex;
                //}
                //if (this.method_3(entity, command))
                //{
                //    VersionExpiredException ex2 = new VersionExpiredException(HdxMessage.GetInstance().ComposeMessage("hdx_entity_01"));
                //    throw ex2;
                //}
                stringBuilder.Append("delete from ");
                stringBuilder.Append(entity.ENTITY_TABLES);
                stringBuilder.Append(" where ");
                stringBuilder.Append(this.method_2(entity));
                //command.CommandText = stringBuilder.ToString();
                //if (comm  and.ExecuteNonQuery() == 0)
                //{
                //    RecordNotFoundException ex3 = new RecordNotFoundException("Record not found");
                //    throw ex3;
                //}
                //this.CloseConnection();

            }
            catch (Exception ex4)
            {
                base.Log(ex4.ToString(), LogLevel.ERROR);
                throw ex4;
            }
            finally
            {

            }
        }
        public abstract AbstractEntity[] PackEntity(object obj);
        public virtual string FieldNameToPropertyName(string field)
        {
            return DbConnectionHelper.FieldNameToPropertyName(field);
        }

        public virtual object ExecuteReader(string sql, string conection_addr)
        {
            DbConnectionHelper.Compress(Encoding.UTF8.GetBytes(""));
            string s = "data=" + HttpUtility.UrlEncode(Convert.ToBase64String(DbConnectionHelper.Compress(Encoding.UTF8.GetBytes(sql + "?Method=ExecuteReader?RequiredTransaction=False"))));
            //string s = "data=" + HttpUtility.UrlEncode(Convert.ToBase64String(Encoding.UTF8.GetBytes(sql + "?Method=ExecuteReader?RequiredTransaction=False")));
            byte[] bytes = Encoding.UTF8.GetBytes(s);
            WebClient client = new WebClient();
            client.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
            byte[] toDecompress = null;
            toDecompress = client.UploadData(conection_addr + "/XCommander.aspx", bytes);
            return SerializationHelper.Deserialize(Encoding.UTF8.GetString(DbConnectionHelper.Decompress(toDecompress)), typeof(DataTable));
        }

        public virtual object ExecuteNonQuery(string sql, string conection_addr)
        {
            string s = "data=" + HttpUtility.UrlEncode(Convert.ToBase64String(DbConnectionHelper.Compress(Encoding.UTF8.GetBytes(sql + "?Method=ExecuteNonQuery?RequiredTransaction=True"))));
            byte[] bytes = Encoding.UTF8.GetBytes(s);
            WebClient client = new WebClient();
            client.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
            byte[] toDecompress = null;
            toDecompress = client.UploadData(conection_addr + "/XCommander.aspx", bytes);
            return SerializationHelper.Deserialize(Encoding.UTF8.GetString(DbConnectionHelper.Decompress(toDecompress)), typeof(int));
        }

        public virtual object MoldChangingSchedule(string sql, string conection_addr)
        {
            string s = "data=" + HttpUtility.UrlEncode(Convert.ToBase64String(DbConnectionHelper.Compress(Encoding.UTF8.GetBytes(sql + "?Method=MoldChangingSchedule?RequiredTransaction=False"))));
            byte[] bytes = Encoding.UTF8.GetBytes(s);
            WebClient client = new WebClient();
            client.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
            byte[] toDecompress = null;


            toDecompress = client.UploadData(conection_addr + "/XCommander.aspx", bytes);
            return SerializationHelper.Deserialize(Encoding.UTF8.GetString(DbConnectionHelper.Decompress(toDecompress)), typeof(DataTable));
        }

        public virtual object ExecuteReader(string sql, string conection_addr, string Method)
        {
            string s = "data=" + HttpUtility.UrlEncode(Convert.ToBase64String(DbConnectionHelper.Compress(Encoding.UTF8.GetBytes(sql + "?Method=" + Method + "?RequiredTransaction=False"))));
            byte[] bytes = Encoding.UTF8.GetBytes(s);
            WebClient client = new WebClient();
            client.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
            byte[] toDecompress = null;


            toDecompress = client.UploadData(conection_addr + "/XCommander.aspx", bytes);
            return SerializationHelper.Deserialize(Encoding.UTF8.GetString(DbConnectionHelper.Decompress(toDecompress)), typeof(DataTable));
        }
    }
}
